﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using LevelEditor.Dao;
using LevelEditor.Objects;
using LevelEditor.Objects.Tiles;
using LevelEditor.Objects.Waypoints;
using LevelEditor.App.Serialization;

namespace LevelEditor.Components.Waypoints
{
    class WaypointsPanel : Panel
    {
        private const int WAYPOINT_DIAMETER = 20;
        private Character edittingChar;
        private Behavior mappedBehavior;
        private WaypointsCollection waypoints = new WaypointsCollection();
        private Rectangle drawingWaypointTile;

        private bool showingWaypoints;
        public bool IsShowingWaypoints
        {
            get { return showingWaypoints; }
        }

        public WaypointsPanel()
            : base()
        {
            this.drawingWaypointTile = new Rectangle();

            this.Visible = false;
            this.Enabled = false;
            this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.Click += WaypointsPanel_Click;
            this.MouseMove += WaypointsPanel_MouseMove;
            this.showingWaypoints = false;
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
                return createParams;
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Nothing=
        }

        void WaypointsPanel_Click(object sender, EventArgs e)
        {
            CreateWaypoint(MousePositionToTilePosition(PointToClient(Cursor.Position)));
        }

        void WaypointsPanel_MouseMove(object sender, MouseEventArgs e)
        {
            drawingWaypointTile = new Rectangle(MousePositionToTilePosition(PointToClient(Cursor.Position)),
                new Size(Tile.CurrentSelectedTile.MyLayer.TileWidth, Tile.CurrentSelectedTile.MyLayer.TileHeight));
        }

        private Point MousePositionToTilePosition(Point position) // center the waypoint on the tile
        {
            if (Tile.CurrentSelectedTile == null) return position;
            position.X = (position.X / Tile.CurrentSelectedTile.MyLayer.TileWidth) * Tile.CurrentSelectedTile.MyLayer.TileWidth;
            position.Y = (position.Y / Tile.CurrentSelectedTile.MyLayer.TileHeight) * Tile.CurrentSelectedTile.MyLayer.TileHeight;

            return position;
        }

        private void CreateWaypoint(Point position)
        {
            position.X += (int)(Tile.CurrentSelectedTile.MyLayer.TileWidth * 0.5f);
            position.Y += (int)(Tile.CurrentSelectedTile.MyLayer.TileHeight * 0.5f);

            Waypoint w = new Waypoint();
            w.location = position;
            w.character = edittingChar;
            w.col = position.X / edittingChar.MyLayer.TileWidth;
            w.row = position.Y / edittingChar.MyLayer.TileHeight;
            if (w.id == 0)
                w.id = 1 + waypoints.Count;

            if (waypoints.Count > 0)
            {
                if (waypoints[waypoints.Count - 1].col != w.col && waypoints[waypoints.Count - 1].row != w.row) return; // tile is in diagonal
                w.previous = waypoints[waypoints.Count - 1];
                waypoints[waypoints.Count - 1].next = w;

                w.idPrevious = waypoints[waypoints.Count - 1].id;
                waypoints[waypoints.Count - 1].idNext = w.id;
            }
            waypoints.Add(w);
                        
        }

        private void DrawCircle(Point position)
        {
            Graphics g = this.CreateGraphics();

            g.FillEllipse(new SolidBrush(Color.Blue), new Rectangle(position, new Size(WAYPOINT_DIAMETER, WAYPOINT_DIAMETER)));

            g.Dispose();
        }

        private void DrawLine(Point p1, Point p2)
        {
            Graphics g = this.CreateGraphics();
            g.DrawLine(new Pen(new SolidBrush(Color.Black)), p1, p2);

            g.Dispose();
        }

        public void ShowWaypoints(WaypointsCollection wayCollection)
        {
            
            this.Visible = true;
            this.waypoints.Clear();
            this.waypoints.AddRange( wayCollection);
            this.showingWaypoints = true;
        }

        public void StopShowingWaypoints()
        {
            this.Disable();
        }

        public bool Enable()
        {
            Disable();
            WaypointsConfiguration waypointsConfig = new WaypointsConfiguration((Character)Tile.CurrentSelectedTile);
            if (waypointsConfig.ShowDialog() == DialogResult.OK)
            {
                this.mappedBehavior = waypointsConfig.SelectedAction;
                this.Visible = true;
                this.Enabled = true;
                this.waypoints = waypointsConfig.Waypoints;
                this.showingWaypoints = false;
                return true;
            }
            
            return false;
        }

        public void Disable()
        {
            if (this.edittingChar != null && !showingWaypoints)
            {
                UtilSerialization.allWaypointsCollections.Add(waypoints);
                int newIdCollection = Util.Util.GetAmountOfWaypointsCollections();
                foreach (Waypoint w in waypoints)
                {
                    if (w.idCollection == 0)
                        w.idCollection = newIdCollection;
                }

                mappedBehavior.Waypoints.Clear();
                mappedBehavior.Waypoints.Name = waypoints.Name;
                mappedBehavior.Waypoints.AddRange(waypoints);
                
                Trigger trigger = this.edittingChar.MyTrigger.Find(delegate(Trigger t)
                {
                    return t.MappedBehavior.Name == mappedBehavior.Name;
                }
                );

                if (trigger == null || this.edittingChar.MyTrigger.Count == 0)
                {
                    this.edittingChar.standAloneBehaviors.Add(mappedBehavior);
                }
                else
                {

                    this.edittingChar.MyTrigger.Find(delegate(Trigger t)
                    {
                        return t.MappedBehavior.Name == mappedBehavior.Name;
                    }
                    ).MappedBehavior.Waypoints.AddRange(this.mappedBehavior.Waypoints);
                }
                

            }
            this.showingWaypoints = false;
            this.Visible = false;
            this.Enabled = false;

            if (this.waypoints != null)
                this.waypoints.Clear();
        }

        public void SetEdittingtCharacter(Character c)
        {
            this.edittingChar = c;
            CreateWaypoint(edittingChar.Location);

        }

        public void DrawWaypoints()
        {
            Graphics g = this.CreateGraphics();
            g.FillRectangle(new SolidBrush(Color.FromArgb(80, Color.SkyBlue)), drawingWaypointTile);
            g.Dispose();

            if (waypoints == null) return;

            for (int k = 0; k < waypoints.Count; k++)
            {
                Waypoint w = waypoints[k];
                
                if (waypoints.Count > 1 && w.next != null)
                {
                    Point p1 = new Point(w.location.X + (int)(WAYPOINT_DIAMETER * 0.5f), w.location.Y + (int)(WAYPOINT_DIAMETER * 0.5f));
                    Point p2 = new Point(w.next.location.X + (int)(WAYPOINT_DIAMETER * 0.5f), w.next.location.Y + (int)(WAYPOINT_DIAMETER * 0.5f));
                    DrawLine(p1, p2);
                }
                DrawCircle(w.location);
            }
        }

        
    }
}
